/* eslint-disable no-plusplus */
/* eslint-disable no-param-reassign */
/* eslint-disable indent */

import { htmlSafe } from './utils'
import { Renderer } from './render'
import { CardRenderer } from './card'

function setColorAlpha(color, alpha) {
  const reg = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/
  const matches = reg.exec(color)
  const r = parseInt(matches[1], 16)
  const g = parseInt(matches[2], 16)
  const b = parseInt(matches[3], 16)
  return `rgba(${r},${g},${b},${alpha})`
}

function renderBoardIcon(board) {
  if (board.icon) {
    return `<i style="color: ${board.color}" class="${board.icon}"></i>`
  }
  return ''
}

export class BoardRenderer extends Renderer {
  render(board) {
    return `<div class="board" data-state="${board.state}">
      <div class="board-inner">
        ${this.renderHeader(board)}
        <div class="board-list-wrapper">
          <ul class="board-list"></ul>
          <div class="ui inverted dimmer">
            <div class="ui loader"></div>
          </div>
          <div class="board-blur-message">
            <p><i class="icon ban"></i></p>
            <p>${this.config.message.stateDisabled}</p>
          </div>
        </div>
    </div>
    </div>`
  }

  renderHeader(board) {
    let headerStyle = ''
    let headerClass = 'board-header'

    if (board.color) {
      if (board.colorTarget === 'background') {
        headerStyle = `background-color: ${setColorAlpha(board.color, 0.04)}`
      } else {
        headerClass += ' has-border'
        headerStyle = `border-color: ${board.color}`
      }
    }
    return `<div class="${headerClass}" style="${headerStyle}">
      <h3 class="board-title" style="color: ${board.color}">
        ${this.renderActions()}
        ${this.renderAvatar(board)}
        ${renderBoardIcon(board)}
        <span class="board-name" style="color: ${board.color}">${htmlSafe(board.name)}</span>
        <span class="issues-count-badge">
          <span class="issues-count">${board.issuesCount}</span>
        </span>        
      </h3>
    </div>`
  }

  renderActions() {
    const config = this.config
    let actions = config.actions

    if (typeof actions === 'function') {
      actions = actions(config)
    }
    return `<div class="right floated board-actions ${config.className.actions}">
        ${actions.map(a => (
          `<button type="button" class="board-action ${a.class}"
            title="${a.title}" data-id="${a.id}">
            <i class="${a.icon}"></i>
          </button>`
        )).join('')}
    </div>`
  }

  renderAvatar(board) {
    if (!board.avatarUrl) {
      return ''
    }
    return `<img class="${this.config.className.avatar} board-avatar"
      alt="${board.state}" src="${this.getAvatarUrl(board.name, board.avatarUrl)}">`
  }

  renderTip(board) {
    const msg = this.config.message

    if (board.loadable) {
      return `<li class="board-tip">
        <span class="ui active mini inline loader"></span>
        ${msg.loading}
      </li>`
    }
    if (board.completed && board.issues.length > 0) {
      return `<li class="board-tip">${msg.allComplete}</li>`
    }
    return `<li class="board-tip">${msg.empty}</li>`
  }
}

export class Board {
  constructor(data, config) {
    this.page = 0
    this.loadable = true
    this.loading = false
    this.completed = false
    this.issues = []

    this.name = data.name
    this.icon = data.icon
    this.state = data.state
    this.color = data.color
    this.colorTarget = data.colorTarget
    this.issuesCount = data.issuesCount || 0
    this.avatarUrl = data.avatarUrl

    this.config = config

    this.renderer = new BoardRenderer(config)
    this.cardRenderer = new CardRenderer(config)

    this.$tip = null
    this.$el = $(this.renderer.render(this))
    this.$dimmer = this.$el.find('.ui.dimmer')
    this.$issues = this.$el.find('.board-list')
    this.$issuesCount = this.$el.find('.issues-count')

    this.$issues.on('scroll', () => {
      this.autoload()
    })
  }

  add(issue) {
    this.issues.push(issue)
    this.issuesCount += 1
    this.$issuesCount.text(this.issuesCount)
  }

  find(id) {
    for (let i = 0; i < this.issues.length; ++i) {
      const issue = this.issues[i]
      if (issue.id === id) {
        return i
      }
    }
    return -1
  }

  get(id) {
    const i = this.find(id)

    if (i >= 0) {
      return this.issues[i]
    }
    return null
  }

  remove(id) {
    const i = this.find(id)

    if (i >= 0) {
      this.issuesCount -= 1
      this.$issuesCount.text(this.issuesCount)
      return this.issues.splice(i, 1)
    }
    return null
  }

  clear() {
    this.page = 0
    this.issues = []
    this.issuesCount = 0
    this.loading = false
    this.loadable = true
    this.completed = false

    this.$issuesCount.text(0)
    this.$issues.empty()
    this.$tip = null
  }

  autoload() {
    if (this.completed) {
      return
    }
    if (!this.$tip || this.$tip.position().top < this.$issues.height()) {
      this.load()
    }
  }

  load() {
    if (this.loading) {
      return false
    }
    this.page += 1
    this.loading = true
    if (this.page === 1) {
      this.$dimmer.addClass('active')
    }
    this.config.onLoad(this, this.onLoadDone.bind(this))
    return true
  }

  onLoadDone(issues, count) {
    this.issuesCount = count
    this.$issuesCount.text(this.issuesCount)
    this.appendIssues(issues)
    if (this.issuesCount > 0) {
      if (issues.length < 1 || this.issuesCount === issues.length) {
        this.loadable = false
        this.completed = true
      } else {
        this.loadable = true
        this.completed = false
      }
    } else {
      this.loadable = false
      this.completed = true
    }
    if (this.page === 1) {
      this.$dimmer.removeClass('active')
    }
    this.loading = false
    this.updateTip()
    this.autoload()
  }

  /* 进行初次加载 */
  firstload() {
    if (this.page > 0) {
      return false
    }
    return this.load()
  }

  /**
   * 更新提示
  */
  updateTip() {
    if (this.$tip) {
      this.$tip.remove()
    }
    this.$tip = $(this.renderer.renderTip(this))
    this.$issues.append(this.$tip)
  }

  createCard(issue) {
    const $card = $(this.cardRenderer.render(issue))
    const onSelect = this.config.onSelect

    if (onSelect) {
      $card.on('click', function (e) {
        let $target = $(e.target)

        if (!$target.is('a')) {
          $target = $target.parent()
        }
        if (!$target.parent().hasClass('card-header')
         && ($target.is('a') && $target.attr('href'))) {
          return
        }
        onSelect(issue, e)
      })
    }
    return this.config.onRender(issue, $card, this.config)
  }

  appendIssue(issue) {
    this.issues.push(issue)
    this.$issues.append(this.createCard(issue))
  }

  prependIssue(issue) {
    this.issuesCount += 1
    this.issues.splice(0, 0, issue);
    this.$issues.prepend(this.createCard(issue))
    this.$issuesCount.text(this.issuesCount)
  }

  updateIssue(issue) {
    const $issue = $(`#${this.config.name}-issue-${issue.id}`)

    if ($issue.length < 1) {
      this.prependIssue(issue)
      return
    }
    $issue.before(this.createCard(issue)).remove()
  }

  /**
   * 直接追加多个任务，不更新任务总数
   * @param {Array} issues 任务列表
   */
  appendIssues(issues) {
    issues.filter(
      issue => this.issues.every(
        boardIssue => boardIssue.id !== issue.id
      )
    ).forEach((issue) => {
      issue[this.config.Key] = this.state
      this.appendIssue(issue)
    })
  }
}

export default null
